package com.huitong.common.security.handler;

import com.huitong.common.core.domain.Result;
import com.huitong.common.core.exception.BusinessException;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MissingPathVariableException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import static org.springframework.http.HttpStatus.*;

/**
 * 全局异常处理器
 *
 * @author fromdrowning
 * @date 2024/3/20 9:57
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 业务异常处理
     *
     * @param e 业务异常
     * @return 响应结果
     */
    @ExceptionHandler(BusinessException.class)
    public Result<Void> handleServiceException(BusinessException e) {
        log.error(e.getMessage());
        return Result.error(e.getMessage());
    }

    /**
     * 系统异常处理
     *
     * @param e       系统异常
     * @param request 请求
     * @return 状态码500 错误提示
     */
    @ExceptionHandler(Exception.class)
    public Result<Void> handleException(Exception e, HttpServletRequest request) {
        log.error("请求路径:{} 系统异常", request.getRequestURI(), e);
        return Result.error(INTERNAL_SERVER_ERROR.value(), "系统内部错误");
    }

    /**
     * 运行时未知异常处理
     *
     * @param e       运行时未知异常
     * @param request 请求
     * @return 状态码500 错误提示
     */
    @ExceptionHandler(RuntimeException.class)
    public Result<Void> handleRuntimeException(RuntimeException e, HttpServletRequest request) {
        log.error("请求路径:{} 未知异常", request.getRequestURI(), e);
        return Result.error(INTERNAL_SERVER_ERROR.value(), "系统内部错误");
    }

    /**
     * 请求方式不支持异常处理
     *
     * @param e       请求方式不支持异常
     * @param request 请求
     * @return 状态码405 错误提示
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public Result<Void> handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException e, HttpServletRequest request) {
        log.error("请求路径:{} 不支持请求:{}", request.getRequestURI(), e.getMethod());
        return Result.error(METHOD_NOT_ALLOWED.value(), "请求方式不支持");
    }

    /**
     * 请求路径中缺少必需的路径变量异常处理
     *
     * @param e       请求路径中缺少必需的路径变量异常
     * @param request 请求
     * @return 状态码400 错误提示
     */
    @ExceptionHandler(MissingPathVariableException.class)
    public Result<Void> handleMissingPathVariableException(MissingPathVariableException e, HttpServletRequest request) {
        log.error("请求路径:{} 缺少必须的路径变量:{}", request.getRequestURI(), e.getVariableName());
        return Result.error(BAD_REQUEST.value(), "请求缺少必需的路径变量");
    }

    /**
     * 请求参数类型不匹配异常处理
     *
     * @param e       请求参数类型不匹配异常
     * @param request 请求
     * @return 状态码400 错误提示
     */
    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    public Result<Void> handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e, HttpServletRequest request) {
        log.error("请求路径:{} 参数类型不匹配:{}", request.getRequestURI(), e.getParameter());
        return Result.error(BAD_REQUEST.value(), "请求参数类型不匹配");
    }
}
